package ycj.learn.concurrent;

import java.util.ArrayList;
import java.util.LinkedList;

/**
 * 实现线程池
 */
public class DefaultThreadPool<Task extends Runnable> implements ThreadPool<Task> {

    /**
     * 最大线程数量
     */
    private static final int MAX_THREAD_NUMBERS = 10;

    /**
     * 初始线程数量
     */
    private static final int INIT_THREAD_NUMBERS = 5;

    /**
     * 最小线程数量
     */
    private static final int MIN_THREAD_NUMBERS = 1;


    /**
     * 任务队列
     */
    private final LinkedList<Task> tasks = new LinkedList<Task>();

    /**
     * 工作线程集合
     */
    private final ArrayList<Worker> workers = new ArrayList<Worker>(MAX_THREAD_NUMBERS);


    public DefaultThreadPool() {

        initWorkers();
    }


    /**
     * 执行任务
     */
    public void execute(Task task) {
        synchronized (tasks) {
            tasks.addLast(task);
            tasks.notify();
        }
    }

    public void shutdown() {
        for (Worker worker : workers) {
            worker.shutdown();
        }
    }

    /**
     * 初始化工作线程
     */
    private void initWorkers() {
        for (int i = 0; i < INIT_THREAD_NUMBERS; i++) {
            Worker worker = new Worker();

            Thread thread = new Thread(worker);

            thread.start();

            workers.add(worker);
        }
    }

    class Worker implements Runnable {

        private volatile boolean running = true;

        public void run() {
            while (running) {
                Task task;

                /**
                 * 从队列里面获取任务,如果队列为空,则一直线程进入等待状态,直到有新任务将其唤醒
                 */
                synchronized (tasks) {
                    while (tasks.isEmpty()) {
                        try {
                            tasks.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            return;
                        }
                    }
                    task = tasks.removeFirst();
                }

                if (null != task) {
                    try {
                        task.run();

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        void shutdown() {
            running = false;
        }
    }

    public static void main(String[] args) {

        DefaultThreadPool<Runnable> threadPool = new DefaultThreadPool<Runnable>();
        for (int i = 0; i < 1000; i++) {
            final int f = i;
            threadPool.execute(() -> System.out.println(f));
        }
    }
}
